/* Measure.h
 *
 * Created on: Mar 12, 2012
 * Author: snirgaz
 */

#ifndef MEASURE_H_
#define MEASURE_H_
#include "HelpLibs/Observable.h"
#include "SSEConf.h"
#include "HelpLibs/QmcParameters.h"
//#include "../HelpLibs/def.h"
#include "HelpLibs/fftwPlane.h"
#include "boost/chrono.hpp"
#include "boost/rational.hpp"
#include <map>
#include <functional>
#include "mathimf.h"
#include <boost/foreach.hpp>
#include <boost/range/algorithm.hpp>
#include "HelpLibs/fftwPlane.h"

using namespace std;
using namespace boost;

typedef boost::chrono::system_clock::time_point TimePoint;
typedef boost::chrono::duration<double, boost::ratio<3600> > Hour;
typedef boost::rational<int> rationalNumber;
class Measure {
protected:
	SSEConf *sseConf_;
public:
	Measure();
	virtual void DoMeasurement()=0;
	virtual bool checkDone() const =0;
	virtual void dumpToFile(hdf5RW &hdf5File) const=0;
	virtual int getNumOfMeasure() const=0;
	virtual void readFromFile(hdf5RW &hdf5File)=0;
	virtual ~Measure();
};
class ProgressBar {
	int totalNumberOfMeasure_;
	ofstream *outFile_;
	double simTime_;
	TimePoint startTime_;
	double pc_;
	double deltaDump_;
public:
	void init(int totalNumberOfMeasure, int minNumOfMeasure, double simTime,
			double deltaDump, ofstream *outFile);
	void update(int numOfMeasure, bool &endTime, bool &dumpFlag);
	void updateMinNumOfMeasure(int minNumOfMeasure);
};
class Measurements {
	typedef boost::ptr_vector<Measure> MeasureVector;
	typedef MeasureVector::iterator MeasureVectorIter;
	int numOfBins_;
private:
	MeasureVector measures_;
	SSEConf *sseConf_;
	ProgressBar progBar_;
	int rate_;
	bool allDone_;
	ofstream *outFile_;
public:
	Measurements();
	~Measurements();
	void init(SSEConf *sseConf, QmcParameters &qmcParameters, ofstream *outFile,
			MTGen *gen);
	void DoMeasurement(bool &endTime, bool &dumpTime);
	bool checkNotDone() const;
	void dump(string outPath) const;
	void read(string outPath);
	void updateMinNumOfMeasure(int totalNumberOfMeasure);
	void updateRate(int const rate);
	int getRate() const;
};

class WindingEnergyMeasure: public Measure {
	Observable<ScalarObs<double> > windX_, windY_, energy_, cv_;
public:
	WindingEnergyMeasure(SSEConf *sseConf, QmcParameters &qmcParameters);
	void DoMeasurement();
	void dumpToFile(hdf5RW &hdf5File) const;
	void readFromFile(hdf5RW &hdf5File);
	bool checkDone() const;
	int getNumOfMeasure() const;
};
class LodounFlourieMeasure: public Measure {
	Observable<VectorObs<double> > LF_;
	UniformReal X_;
	int numOfOmega_, numOfSites_;
	fftwPlan fPlane_;
	ublas::vector<double> gOmega_, k_;
	vector<double> XCorr_, Xp1_, Xp2_, tau_;
	double beta_;
public:
	LodounFlourieMeasure(SSEConf *sseConf, QmcParameters &qmcParameters,
			MTGen *rng);
	void DoMeasurement();
	void dumpToFile(hdf5RW &hdf5File) const;
	void readFromFile(hdf5RW &hdf5File);
	bool checkDone() const;
	int getNumOfMeasure() const;
};
class HcorrMeasure: public Measure {
	ArrayObservableBin<double,1> HCorr_;
	UniformReal X_;
	int numOfOmega_, numOfSites_;
	fftwPlan fPlane_;
	ublas::vector<double> gOmega_, k_;
	vector<double> XCorr_, Xp1_, Xp2_, tau_;
	double beta_;
public:
	HcorrMeasure(SSEConf *sseConf, QmcParameters &qmcParameters, MTGen *rng);
	void DoMeasurement();
	void dumpToFile(hdf5RW &hdf5File) const;
	void readFromFile(hdf5RW &hdf5File);
	bool checkDone() const;
	int getNumOfMeasure() const;
};
class StaggeredMeasure: public Measure {
	Observable<ScalarObs<double>> mz_;
	int L_;
public:
	StaggeredMeasure(SSEConf *sseConf, QmcParameters &qmcParameters);
	void DoMeasurement();
	void dumpToFile(hdf5RW &hdf5File) const;
	void readFromFile(hdf5RW &hdf5File);
	bool checkDone() const;
	int getNumOfMeasure() const;
};
#endif /* MEASURE_H_ */
